/**
 * 注解执行是有顺序的， 顺序如下
 * 1. 先执行带参数的注解
 * 2. 再按照 出现顺序 执行 属性或 方法的注解
 * 3. 最后按照 栈（先书写后执行） 类的注解
 */
@fn
@fn3
@fn2(10) // 这个可以理解为执行了 fn2(10)的函数
class MyClass {
  @noEnumerable name = 'huangbiao' // name 无法被遍历到
  @readOnly message = 'hello' // message 无法被修改
}

function fn(target) {
  console.log('fn')
  target.foo = 'bar'
}

function fn2(value) {
  console.log('fn2')
  return function (target) {
    target.count = value
  }
}

function fn3(target) {
  console.log('fn3', target)
  target.prototype.foo = 'baz'
}

function readOnly(target, name, descriptor) {
  console.log('fn4')
  console.log('target', target) // 目标类的.prototype
  console.log('name', name) // 被修饰的类成员名称
  /**
  configurable: true  // 默认值为true 当设置为false 则理解为该属性不可删除不可修改
  enumerable: true  // 默认值为true 当设置为false 则理解我改属性只读
  initializer: ƒ ()
  writable: true // 默认值为true 当设置为false 则理解为无法枚举 遍历属性时无法将该属性取出
   */
  console.log('descriptor', descriptor) // 被修饰类成员的描述对象
  descriptor.writable = false
}

function noEnumerable(target, name, descriptor) {
  console.log('fn5')
  console.log('target', target) // 目标类的.prototype
  console.log('name', name) // 被修饰的类成员名称
  /**
  configurable: true  // 默认值为true 当设置为false 则理解为该属性不可删除不可修改
  enumerable: true  // 默认值为true 当设置为false 则理解我改属性只读
  initializer: ƒ ()
  writable: true // 默认值为true 当设置为false 则理解为无法枚举 遍历属性时无法将该属性取出
   */
  console.log('descriptor', descriptor) // 被修饰类成员的描述对象
  descriptor.enumerable = false
}

console.log('MyClass.foo =>', MyClass.foo) // => bar
console.log('MyClass.count =>', MyClass.count) // => bar
console.log('new MyClass().foo => ', new MyClass().foo) // => baz

const obj = new MyClass()
// obj.message = 'world'
// console.log('obj.message => ', obj.message)

for (var key in obj) {
   console.log('key, obj[key]', key, obj[key])
}










